package gu.sql2java;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.google.common.base.Strings;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * 实现日期类型字段值的类型转换
 * @author guyadong
 *
 */
class ResultSetTypeCastSqliteImpl implements ResultSetTypeCast {
	static final ResultSetTypeCastSqliteImpl SQLITE_CAST = new ResultSetTypeCastSqliteImpl();
    /** ISO8601时间格式 */
    static final String ISO8601_FORMATTER_STR = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
    
    /** 用于SQL语句的时间戳格式转换格式 */
    static final String TIMESTAMP_FORMATTER_STR = "yyyy-MM-dd HH:mm:ss";
    
    /** 日期转换格式 */
    static final String DATE_FORMATTER_STR = "yyyy-MM-dd";
	private ResultSetTypeCastSqliteImpl() {
	}

	private static Date toDate(String date) throws ParseException{
		if(Strings.isNullOrEmpty(date)){
			return null;
		}
		try {
			return new SimpleDateFormat(TIMESTAMP_FORMATTER_STR).parse(date);
		} catch (ParseException e) {
			try {
				return new SimpleDateFormat(ISO8601_FORMATTER_STR).parse(date);
			} catch (ParseException e2) {
				return new SimpleDateFormat(DATE_FORMATTER_STR).parse(date);
			}
		}
	}
	
	private static Object valueOf(String input,Class<?>target) throws Exception{
			Method m = target.getMethod("valueOf", String.class);
			if(Modifier.isStatic(m.getModifiers())){
				return m.invoke(null, input);
			}
			throw new ClassCastException("not suported valueOf(String)  for " + target);
	}
	@Override
	public Object cast(Object input, Type target) throws ClassCastException {
		if(null ==input){
			return input;
		}
		checkArgument(input instanceof String, "input must be string");
		checkArgument(null !=target, "target is null");
		String v = (String)input;
		try{
			if(URL.class.equals(target)){
				return new URL(v);
			}
			if(URI.class.equals(target)){
				return new URI(v);
			}
			if(Date.class.equals(target)){
				return toDate(v);
			}
			
			// 尝试调用valueOf(String)方法
			if(target instanceof Class<?>){
				return valueOf(v,(Class<?>)target);
			}
			throw new ClassCastException("Conversion not supported for type " + target);
		}catch (Exception e) {
			throw new ClassCastException("Conversion not supported for type " + target + "caused by " + e.getMessage());
		}
	}

}
